package com.duobaoyu.dby.supply.biz.service.config.impl;

import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.duobaoyu.dby.common.core.constant.StringPool;
import com.duobaoyu.dby.supply.biz.converter.PreWarningConfigConverter;
import com.duobaoyu.dby.supply.biz.service.config.PreWarningConfigService;
import com.duobaoyu.dby.supply.biz.strategy.AbstractPreWarningCountStrategy;
import com.duobaoyu.dby.supply.common.biz.bo.config.PreWarningConfigGroupBO;
import com.duobaoyu.dby.supply.common.biz.bo.config.PreWarningConfigSelectBO;
import com.duobaoyu.dby.supply.common.biz.bo.config.PreWarningReminderConfigBO;
import com.duobaoyu.dby.supply.common.biz.dto.config.PreWarningConditionDTO;
import com.duobaoyu.dby.supply.common.biz.dto.config.PreWarningUpdateDTO;
import com.duobaoyu.dby.supply.core.common.exception.CustomAssert;
import com.duobaoyu.dby.supply.core.framework.util.FrameworkUtils;
import com.duobaoyu.dby.supply.db.entity.config.PreWarningConfig;
import com.duobaoyu.dby.supply.db.repository.config.PreWarningConfigRepository;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import lombok.RequiredArgsConstructor;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.*;
import java.util.concurrent.ConcurrentMap;
import java.util.stream.Collectors;

/**
 * @author liyang
 * @version 1.0.0
 * @ClassName PreWarningConfigServiceImpl
 * @createTime 12:59:00 2023/10/16
 */
@Service
@RequiredArgsConstructor
public class PreWarningConfigServiceImpl implements PreWarningConfigService {

    private final PreWarningConfigConverter preWarningConfigConverter;
    private final PreWarningConfigRepository preWarningConfigRepository;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updatePreWarningConfig(PreWarningUpdateDTO preWarningUpdate) {
        String mobile = Optional.ofNullable(preWarningUpdate.getMobiles()).orElse(Collections.emptyList())
                .stream().collect(Collectors.joining(StringPool.COMMA));
        PreWarningConfig preWarningConfig = preWarningConfigRepository.getById(preWarningUpdate.getPreWarningConfigId());
        CustomAssert.notNull(preWarningConfig,"配置不存在");
        boolean update = preWarningConfigRepository.update(Wrappers.lambdaUpdate(PreWarningConfig.class)
                .eq(PreWarningConfig::getId, preWarningUpdate.getPreWarningConfigId())
                .set(PreWarningConfig::getUpdateTime, LocalDateTime.now())
                .set(PreWarningConfig::getMobile, StrUtil.isEmpty(mobile) ? null : mobile));
        if(update) {
            // 同一类预警下只能配置一个时间节点收到短信
            preWarningConfigRepository.update(Wrappers.lambdaUpdate(PreWarningConfig.class)
                    .ne(PreWarningConfig::getId, preWarningUpdate.getPreWarningConfigId())
                    .eq(PreWarningConfig::getGroupCode,preWarningConfig.getGroupCode())
                    .set(PreWarningConfig::getUpdateTime, LocalDateTime.now())
                    .set(PreWarningConfig::getMobile, null));
        }
        return update;
    }

    @Override
    public List<PreWarningConfigGroupBO> listPreWarningConfigGroup() {
        List<PreWarningConfig> preWarningConfigs = preWarningConfigRepository.list();
        if (CollectionUtils.isEmpty(preWarningConfigs)) {
            return Collections.emptyList();
        }
        ConcurrentMap<Long, Long> preWarningCount = Maps.newConcurrentMap();
        preWarningConfigs.stream().parallel()
                .forEach(preWarningConfig -> {
                    Long count = FrameworkUtils.strategyInstance(AbstractPreWarningCountStrategy.class, preWarningConfig.getType()).strategyHandler(preWarningConfig);
                    preWarningCount.put(preWarningConfig.getId(),count);
                });
        Map<Integer, List<PreWarningConfig>> preWarningConfigGroup = preWarningConfigs.stream().collect(Collectors.groupingBy(PreWarningConfig::getGroupCode));
        ArrayList<PreWarningConfigGroupBO> preWarningConfigGroupInfos = Lists.newArrayList();
        preWarningConfigGroup.forEach((k, v) -> {
            PreWarningConfigGroupBO preWarningConfig = new PreWarningConfigGroupBO();
            preWarningConfig.setGroupCode(k);
            preWarningConfig.setGroupName(v.stream().findFirst().map(PreWarningConfig::getGroupName).orElse(StringPool.EMPTY));
            List<PreWarningConfigGroupBO.Item> items = preWarningConfigConverter.toPrePreWarningConfigGroup(v,preWarningCount);
            preWarningConfig.setItemList(items);
            preWarningConfigGroupInfos.add(preWarningConfig);
        });
        return preWarningConfigGroupInfos;
    }

    @Override
    public List<PreWarningConfigSelectBO> getPreWarningSelectData(Integer queryScene) {
        List<PreWarningConfig> preWarningConfigs = preWarningConfigRepository.list(Wrappers.lambdaQuery(PreWarningConfig.class)
                .apply(Objects.nonNull(queryScene), "`query_biz_scene` & {0} = `query_biz_scene`", queryScene));
        if (CollectionUtils.isEmpty(preWarningConfigs)) {
            return Collections.emptyList();
        }
        ArrayList<PreWarningConfigSelectBO> root = Lists.newArrayList();
        Map<Integer, List<PreWarningConfig>> preWarningConfigGroup = preWarningConfigs.stream().collect(Collectors.groupingBy(PreWarningConfig::getGroupCode));
        preWarningConfigGroup.forEach((k, v) -> {
            PreWarningConfigSelectBO to = new PreWarningConfigSelectBO();
            to.setId(k.longValue());
            to.setName(v.stream().findFirst().map(PreWarningConfig::getGroupName).orElse(StringPool.EMPTY));
            List<PreWarningConfigSelectBO> children = v.stream().sorted().map(item -> {
                PreWarningConfigSelectBO child = new PreWarningConfigSelectBO();
                child.setId(item.getId());
                child.setName(item.getItemDescribe());
                return child;
            }).collect(Collectors.toList());
            to.setChildren(children);
            root.add(to);
        });
        return root;
    }

    @Override
    public PreWarningConfig getPreWarningConfig(Long id) {
        return preWarningConfigRepository.getById(id);
    }

	@Override
    public PreWarningReminderConfigBO getPreWarningReminderConfig(Integer groupCode) {
        List<PreWarningConfig> preWarningConfigs = preWarningConfigRepository.lambdaQuery().eq(PreWarningConfig::getGroupCode,groupCode).list()
                .stream().sorted().collect(Collectors.toList());
        if(CollectionUtils.isEmpty(preWarningConfigs)) {
            return null;
        }
        PreWarningReminderConfigBO preWarningReminderConfig = new PreWarningReminderConfigBO();
        preWarningReminderConfig.setGroupCode(preWarningConfigs.stream().findFirst().map(PreWarningConfig::getGroupCode).orElse(null));
        preWarningReminderConfig.setGroupName(preWarningConfigs.stream().findFirst().map(PreWarningConfig::getGroupName).orElse(StringPool.EMPTY));
        ArrayList<PreWarningConfigSelectBO> selectOptions = Lists.newArrayList();
        for (PreWarningConfig preWarningConfig : preWarningConfigs) {
            PreWarningConfigSelectBO preWarningConfigSelect = new PreWarningConfigSelectBO();
            preWarningConfigSelect.setId(preWarningConfig.getId());
            preWarningConfigSelect.setName(preWarningConfig.getItemDescribe());
            List<String> mobiles = preWarningConfigConverter.mobileStrToList(preWarningConfig.getMobile());
            if(CollectionUtils.isNotEmpty(mobiles)) {
                preWarningReminderConfig.setMobiles(mobiles);
                preWarningConfigSelect.setSelected(true);
            }
            selectOptions.add(preWarningConfigSelect);
        }
        preWarningReminderConfig.setSelectData(selectOptions);
        return preWarningReminderConfig;
    }

	@Override
	public PreWarningConditionDTO getPreWarningCondition(Long id) {
		PreWarningConfig preWarningConfig = preWarningConfigRepository.getById(id);
		return preWarningConfigConverter.parsePreWarningCondition(preWarningConfig);
	}
}
